<template>
  <div :class="wrapperClasses">
    <!-- 标签 -->
    <label v-if="label" :for="inputId" :class="labelClasses">
      {{ label }}
      <span v-if="required" class="base-input__required">*</span>
    </label>

    <!-- 输入框容器 -->
    <div :class="inputWrapperClasses">
      <!-- 前缀图标 -->
      <div v-if="prefixIcon || $slots.prefix" class="base-input__prefix">
        <slot name="prefix">
          <el-icon v-if="prefixIcon">
            <component :is="prefixIcon" />
          </el-icon>
        </slot>
      </div>

      <!-- 输入框 -->
      <input
        v-if="type !== 'textarea'"
        :id="inputId"
        ref="inputRef"
        :class="inputClasses"
        :type="inputType"
        :value="modelValue"
        :placeholder="placeholder"
        :disabled="disabled"
        :readonly="readonly"
        :maxlength="maxlength"
        :minlength="minlength"
        :max="max"
        :min="min"
        :step="step"
        :autocomplete="autocomplete"
        @input="handleInput"
        @change="handleChange"
        @focus="handleFocus"
        @blur="handleBlur"
        @keydown="handleKeydown"
        @keyup="handleKeyup"
      />

      <!-- 文本域 -->
      <textarea
        v-else
        :id="inputId"
        ref="inputRef"
        :class="inputClasses"
        :value="modelValue"
        :placeholder="placeholder"
        :disabled="disabled"
        :readonly="readonly"
        :maxlength="maxlength"
        :minlength="minlength"
        :rows="rows"
        :cols="cols"
        @input="handleInput"
        @change="handleChange"
        @focus="handleFocus"
        @blur="handleBlur"
        @keydown="handleKeydown"
        @keyup="handleKeyup"
      />

      <!-- 后缀图标 -->
      <div v-if="suffixIcon || $slots.suffix || showPassword || clearable" class="base-input__suffix">
        <!-- 清除按钮 -->
        <button
          v-if="clearable && modelValue && !disabled && !readonly"
          type="button"
          class="base-input__clear"
          @click="handleClear"
        >
          <el-icon><Close /></el-icon>
        </button>

        <!-- 密码显示切换 -->
        <button
          v-if="showPassword && type === 'password'"
          type="button"
          class="base-input__password-toggle"
          @click="togglePasswordVisibility"
        >
          <el-icon>
            <component :is="passwordVisible ? 'Hide' : 'View'" />
          </el-icon>
        </button>

        <!-- 自定义后缀 -->
        <slot name="suffix">
          <el-icon v-if="suffixIcon">
            <component :is="suffixIcon" />
          </el-icon>
        </slot>
      </div>

      <!-- 字数统计 -->
      <div v-if="showWordLimit && maxlength" class="base-input__count">
        {{ (modelValue || '').length }}/{{ maxlength }}
      </div>
    </div>

    <!-- 帮助文本 -->
    <div v-if="helpText || errorMessage" :class="helpTextClasses">
      {{ errorMessage || helpText }}
    </div>
  </div>
</template>

<script setup>
import { ref, computed, nextTick, watch, useSlots } from 'vue'
import { Close, Hide, View } from '@element-plus/icons-vue'

const slots = useSlots()

const props = defineProps({
  // v-model
  modelValue: {
    type: [String, Number],
    default: ''
  },
  // 输入框类型
  type: {
    type: String,
    default: 'text',
    validator: (value) => ['text', 'password', 'email', 'number', 'tel', 'url', 'search', 'textarea'].includes(value)
  },
  // 标签
  label: {
    type: String,
    default: ''
  },
  // 占位符
  placeholder: {
    type: String,
    default: ''
  },
  // 是否禁用
  disabled: {
    type: Boolean,
    default: false
  },
  // 是否只读
  readonly: {
    type: Boolean,
    default: false
  },
  // 是否必填
  required: {
    type: Boolean,
    default: false
  },
  // 大小
  size: {
    type: String,
    default: 'medium',
    validator: (value) => ['small', 'medium', 'large'].includes(value)
  },
  // 状态
  status: {
    type: String,
    default: 'default',
    validator: (value) => ['default', 'success', 'warning', 'error'].includes(value)
  },
  // 错误信息
  errorMessage: {
    type: String,
    default: ''
  },
  // 帮助文本
  helpText: {
    type: String,
    default: ''
  },
  // 前缀图标
  prefixIcon: {
    type: [String, Object],
    default: null
  },
  // 后缀图标
  suffixIcon: {
    type: [String, Object],
    default: null
  },
  // 是否可清除
  clearable: {
    type: Boolean,
    default: false
  },
  // 是否显示密码切换
  showPassword: {
    type: Boolean,
    default: false
  },
  // 是否显示字数限制
  showWordLimit: {
    type: Boolean,
    default: false
  },
  // 最大长度
  maxlength: {
    type: [String, Number],
    default: null
  },
  // 最小长度
  minlength: {
    type: [String, Number],
    default: null
  },
  // 数字输入最大值
  max: {
    type: [String, Number],
    default: null
  },
  // 数字输入最小值
  min: {
    type: [String, Number],
    default: null
  },
  // 数字输入步长
  step: {
    type: [String, Number],
    default: null
  },
  // 自动完成
  autocomplete: {
    type: String,
    default: 'off'
  },
  // 文本域行数
  rows: {
    type: [String, Number],
    default: 3
  },
  // 文本域列数
  cols: {
    type: [String, Number],
    default: null
  }
})

const emit = defineEmits(['update:modelValue', 'input', 'change', 'focus', 'blur', 'keydown', 'keyup', 'clear'])

// 响应式数据
const inputRef = ref()
const isFocused = ref(false)
const passwordVisible = ref(false)

// 生成唯一ID
const inputId = computed(() => `base-input-${Math.random().toString(36).substr(2, 9)}`)

// 实际输入类型
const inputType = computed(() => {
  if (props.type === 'password' && props.showPassword) {
    return passwordVisible.value ? 'text' : 'password'
  }
  return props.type === 'textarea' ? 'text' : props.type
})

// 样式类名
const wrapperClasses = computed(() => {
  const classes = ['base-input']
  
  classes.push(`base-input--${props.size}`)
  classes.push(`base-input--${props.status}`)
  
  if (props.disabled) classes.push('base-input--disabled')
  if (props.readonly) classes.push('base-input--readonly')
  if (isFocused.value) classes.push('base-input--focused')
  if (props.errorMessage) classes.push('base-input--error')
  
  return classes
})

const labelClasses = computed(() => {
  const classes = ['base-input__label']
  
  if (props.required) classes.push('base-input__label--required')
  if (props.disabled) classes.push('base-input__label--disabled')
  
  return classes
})

const inputWrapperClasses = computed(() => {
  const classes = ['base-input__wrapper']

  if (props.prefixIcon || slots.prefix) classes.push('base-input__wrapper--has-prefix')
  if (props.suffixIcon || slots.suffix || props.showPassword || props.clearable) classes.push('base-input__wrapper--has-suffix')

  return classes
})

const inputClasses = computed(() => {
  const classes = ['base-input__control']
  
  if (props.type === 'textarea') classes.push('base-input__control--textarea')
  
  return classes
})

const helpTextClasses = computed(() => {
  const classes = ['base-input__help']
  
  if (props.errorMessage) classes.push('base-input__help--error')
  
  return classes
})

// 事件处理
const handleInput = (event) => {
  const value = event.target.value
  emit('update:modelValue', value)
  emit('input', value, event)
}

const handleChange = (event) => {
  emit('change', event.target.value, event)
}

const handleFocus = (event) => {
  isFocused.value = true
  emit('focus', event)
}

const handleBlur = (event) => {
  isFocused.value = false
  emit('blur', event)
}

const handleKeydown = (event) => {
  emit('keydown', event)
}

const handleKeyup = (event) => {
  emit('keyup', event)
}

const handleClear = () => {
  emit('update:modelValue', '')
  emit('clear')
  nextTick(() => {
    inputRef.value?.focus()
  })
}

const togglePasswordVisibility = () => {
  passwordVisible.value = !passwordVisible.value
  nextTick(() => {
    inputRef.value?.focus()
  })
}

// 公开方法
const focus = () => {
  inputRef.value?.focus()
}

const blur = () => {
  inputRef.value?.blur()
}

const select = () => {
  inputRef.value?.select()
}

defineExpose({
  focus,
  blur,
  select,
  inputRef
})
</script>

<style scoped>
.base-input {
  display: flex;
  flex-direction: column;
  gap: var(--spacing-xs);
}

.base-input__label {
  font-size: var(--font-size-sm);
  font-weight: var(--font-weight-medium);
  color: var(--color-text-primary);
  line-height: var(--line-height-tight);
}

.base-input__label--disabled {
  color: var(--color-text-tertiary);
}

.base-input__required {
  color: var(--color-error);
  margin-left: 2px;
}

.base-input__wrapper {
  position: relative;
  display: flex;
  align-items: center;
  background: #ffffff;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
  transition: 0.2s;
  overflow: hidden;
}

.base-input__wrapper:hover:not(.base-input--disabled .base-input__wrapper) {
  border-color: #c0c4cc;
}

.base-input--focused .base-input__wrapper {
  border-color: #409eff;
  outline: none;
}

.base-input--error .base-input__wrapper {
  border-color: var(--color-error);
}

.base-input--error.base-input--focused .base-input__wrapper {
  box-shadow: 0 0 0 3px var(--color-error-100);
}

.base-input--disabled .base-input__wrapper {
  background: var(--color-bg-tertiary);
  border-color: var(--color-border-light);
  cursor: not-allowed;
}

.base-input__control {
  flex: 1;
  padding: 0 15px;
  height: 40px;
  font-family: inherit;
  font-size: 14px;
  line-height: 40px;
  color: #606266;
  background: transparent;
  border: none;
  outline: none;
  resize: none;
}

.base-input__control::placeholder {
  color: #c0c4cc;
}

.base-input__control:disabled {
  color: #c0c4cc;
  cursor: not-allowed;
  background: #f5f7fa;
}

.base-input__control--textarea {
  min-height: 80px;
  resize: vertical;
}

/* 大小变体 */
.base-input--small .base-input__control {
  height: 32px;
  line-height: 32px;
  padding: 0 15px;
  font-size: 12px;
}

.base-input--large .base-input__control {
  height: 40px;
  line-height: 40px;
  padding: 0 15px;
  font-size: 14px;
}

/* 前缀和后缀 */
.base-input__prefix,
.base-input__suffix {
  display: flex;
  align-items: center;
  padding: 0 var(--spacing-md);
  color: var(--color-text-secondary);
}

.base-input__wrapper--has-prefix .base-input__control {
  padding-left: 0;
}

.base-input__wrapper--has-suffix .base-input__control {
  padding-right: 0;
}

.base-input__clear,
.base-input__password-toggle {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  padding: 0;
  margin: 0 var(--spacing-xs);
  color: var(--color-text-tertiary);
  background: transparent;
  border: none;
  border-radius: var(--radius-sm);
  cursor: pointer;
  transition: var(--transition-fast);
}

.base-input__clear:hover,
.base-input__password-toggle:hover {
  color: var(--color-text-secondary);
  background: var(--color-bg-tertiary);
}

.base-input__count {
  position: absolute;
  right: var(--spacing-md);
  bottom: var(--spacing-sm);
  font-size: var(--font-size-xs);
  color: var(--color-text-tertiary);
  pointer-events: none;
}

.base-input__help {
  font-size: var(--font-size-xs);
  line-height: var(--line-height-tight);
  color: var(--color-text-secondary);
}

.base-input__help--error {
  color: var(--color-error);
}

/* 响应式设计 */
@media (max-width: 640px) {
  .base-input--large .base-input__control {
    padding: var(--spacing-md) var(--spacing-lg);
    font-size: var(--font-size-base);
  }
}
</style>
